package org.chen.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.chen.common.exception.ServiceException;
import org.chen.client.CategoryFeignClient;
import org.chen.mapper.ArticleRepository;
import org.chen.mapper.CrawlerTaskRepository;
import org.chen.domain.Article;
import org.chen.domain.CrawlerTask;
import org.chen.domain.dto.BatchDeleteDTO;
import org.chen.domain.dto.CrawlerStatistics;
import org.chen.domain.dto.CrawlerStatisticsDTO;
import org.chen.domain.vo.CategoryVO;
import org.chen.domain.vo.CrawlerResult;
import org.chen.domain.vo.CrawlerTaskVO;
import org.chen.service.CrawlerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class CrawlerTaskService {
    
    private final List<CrawlerService> crawlerServices;
    private final CrawlerTaskRepository taskRepository;
    private final ArticleRepository articleRepository;

    @Autowired
    private CategoryFeignClient categoryFeignClient;

    public Page<CrawlerTaskVO> getTaskPage(int current, int size, String source, String category, Boolean scheduled) {
        // 创建查询条件
        LambdaQueryWrapper<CrawlerTask> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(source)) {
            wrapper.eq(CrawlerTask::getSource, source);
        }

        if (StringUtils.hasText(category)) {
            wrapper.eq(CrawlerTask::getCategory, category);
        }

        if (scheduled != null) {
            wrapper.eq(CrawlerTask::getScheduled, scheduled);
        }

        wrapper.orderByDesc(CrawlerTask::getStartTime);

        // 执行分页查询
        Page<CrawlerTask> page = taskRepository.selectPage(new Page<>(current, size), wrapper);

        // 转换为VO
        List<CrawlerTaskVO> records = page.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());

        // 构建返回结果
        Page<CrawlerTaskVO> result = new Page<>();
        result.setRecords(records);
        result.setTotal(page.getTotal());
        result.setCurrent(page.getCurrent());
        result.setSize(page.getSize());
        
        return result;
    }

    public CrawlerResult executeTask(CrawlerTask task) {
        // 查找对应的爬虫服务
        CrawlerService service = crawlerServices.stream()
                .filter(s -> s.getSourceName().equals(task.getSource()) && s.isSourceAvailable())
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("Invalid or unavailable source: " + task.getSource()));

        // 1. 验证分类ID
        CategoryVO category = categoryFeignClient.getCategory(task.getCategoryId()).getData();
        if (category == null) {
            throw new ServiceException("分类不存在");
        }
        // 保存任务记录
        task.setStartTime(LocalDateTime.now());
        task.setCategoryPath(category.getPath());    // 设置分类路径
        taskRepository.insert(task);

        try {
            // 执行爬虫任务
            CrawlerResult result = service.crawl(task);
            
            // 更新任务状态
            task.setEndTime(LocalDateTime.now());
            task.setSuccess(result.getSuccess());
            task.setFailed(result.getFailed());
            task.setStatus(result.getFailed() == 0 ? "SUCCESS" : "PARTIAL");
            taskRepository.updateById(task);
            
            return result;
        } catch (Exception e) {
            log.error("Task execution failed: {}", e.getMessage(), e);
            
            // 更新任务状态为失败
            task.setEndTime(LocalDateTime.now());
            task.setStatus("FAILED");
            task.getErrors().add(e.getMessage());
            taskRepository.updateById(task);
            
            throw e;
        }
    }

    public CrawlerTaskVO getTaskDetail(String taskId) {
        CrawlerTask task = taskRepository.selectById(taskId);
        if (task == null) {
            throw new IllegalArgumentException("Task not found: " + taskId);
        }
        return convertToVO(task);
    }

    public CrawlerStatistics getStatistics() {
        LocalDateTime today = LocalDate.now().atStartOfDay();
        
        // 统计任务数据
        Long totalTasks = taskRepository.selectCount(null);
        Long successTasks = taskRepository.selectCount(
            new LambdaQueryWrapper<CrawlerTask>()
                .eq(CrawlerTask::getStatus, "SUCCESS")
        );
        Long failedTasks = taskRepository.selectCount(
            new LambdaQueryWrapper<CrawlerTask>()
                .eq(CrawlerTask::getStatus, "FAILED")
        );
        Long todayTasks = taskRepository.selectCount(
            new LambdaQueryWrapper<CrawlerTask>()
                .ge(CrawlerTask::getStartTime, today)
        );
        
        // 统计文章数据
        Long totalArticles = articleRepository.selectCount(new QueryWrapper<Article>().ne("source","admin"));
        Long todayArticles = articleRepository.selectCount(
            new LambdaQueryWrapper<Article>()
                .ge(Article::getCreateTime, today)
        );
        
        // 按来源统计
        Map<String, Long> articlesBySource = articleRepository.countBySource();
        Map<String, Long> tasksBySource = taskRepository.countBySource();
        
        return CrawlerStatistics.builder()
                .totalTasks(totalTasks)
                .successTasks(successTasks)
                .failedTasks(failedTasks)
                .totalArticles(totalArticles)
                .todayTasks(todayTasks)
                .todayArticles(todayArticles)
                .articlesBySource(articlesBySource)
                .tasksBySource(tasksBySource)
                .build();
    }

    private CrawlerTaskVO convertToVO(CrawlerTask task) {
        return CrawlerTaskVO.builder()
                .taskId(task.getTaskId())
                .source(task.getSource())
                .targetCount(task.getTargetCount())
                .scheduled(task.getScheduled())
                .startTime(task.getStartTime().format(
                        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .endTime(task.getEndTime() == null ? "" : task.getEndTime().format(
                        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .duration(task.getDuration())
                .category(task.getCategory())
                .status(task.getStatus())
                .success(task.getSuccess())
                .failed(task.getFailed())
                .errors(task.getErrors())
                .build();
    }

    public void deleteTaskById(String id) {
        // 检查文章状态，只有未处理的文章才能删除
        CrawlerTask crawlerTask = taskRepository.selectById(id);
        if (crawlerTask == null) {
            throw new ServiceException("文章不存在");
        }

        taskRepository.deleteById(id);
    }

    public void batchDelete(BatchDeleteDTO request) {
        taskRepository.deleteByIds(request.getIds());
    }

    public CrawlerStatisticsDTO getStatisticsDashboard() {
        LocalDateTime today = LocalDate.now().atStartOfDay();
        LocalDateTime weekStart = LocalDate.now().atStartOfDay().minusWeeks(1);

        return CrawlerStatisticsDTO.builder()
                .totalTasks(countTotalTasks())
                .successTasks(countTasksByStatus("SUCCESS"))
                .failedTasks(countTasksByStatus("FAILED"))
                .totalArticles(countTotalArticles())
                .pendingArticles(countPendingArticles())
                .todayTasks(countTasksAfterTime(today))
                .todayArticles(countArticlesAfterTime(today))
                .weekTasks(countTasksAfterTime(weekStart))
                .weekArticles(countArticlesAfterTime(weekStart))
                .build();
    }

    /**
     * 获取最近任务列表
     */
    public List<CrawlerTaskVO> getRecentTasks(int limit) {
        LambdaQueryWrapper<CrawlerTask> wrapper = new LambdaQueryWrapper<CrawlerTask>()
                .orderByDesc(CrawlerTask::getStartTime)
                .last("LIMIT " + limit);

        return taskRepository.selectList(wrapper)
                .stream()
                .map(this::convertToTaskVO)
                .collect(Collectors.toList());
    }

    /**
     * 获取任务趋势数据
     */
    public Map<String, Integer> getTaskTrend(LocalDateTime startTime, LocalDateTime endTime) {
        // 获取时间段内的任务数据
        List<CrawlerTask> tasks = taskRepository.selectList(
                new LambdaQueryWrapper<CrawlerTask>()
                        .between(CrawlerTask::getStartTime, startTime, endTime)
        );

        // 计算各种统计数据
        int total = tasks.size();
        int success = (int) tasks.stream()
                .filter(task -> "SUCCESS".equals(task.getStatus()))
                .count();
        int failed = (int) tasks.stream()
                .filter(task -> "FAILED".equals(task.getStatus()))
                .count();
        int pending = (int) tasks.stream()
                .filter(task -> "PENDING".equals(task.getStatus()))
                .count();

        return Map.of(
                "total", total,
                "success", success,
                "failed", failed,
                "pending", pending
        );
    }

    // 辅助方法
    private Long countTotalTasks() {
        return taskRepository.selectCount(null);
    }

    private Long countTasksByStatus(String status) {
        return taskRepository.selectCount(
                new LambdaQueryWrapper<CrawlerTask>()
                        .eq(CrawlerTask::getStatus, status)
        );
    }

    private Long countTotalArticles() {
        return articleRepository.selectCount(null);
    }

    private Long countPendingArticles() {
        return articleRepository.selectCount(
                new LambdaQueryWrapper<Article>()
                        .eq(Article::getStatus,1)
        );
    }

    private Long countTasksAfterTime(LocalDateTime time) {
        return taskRepository.selectCount(
                new LambdaQueryWrapper<CrawlerTask>()
                        .ge(CrawlerTask::getStartTime, time)
        );
    }

    private Long countArticlesAfterTime(LocalDateTime time) {
        return articleRepository.selectCount(
                new LambdaQueryWrapper<Article>()
                        .ge(Article::getCreateTime, time)
        );
    }

    private CrawlerTaskVO convertToTaskVO(CrawlerTask task) {
        return CrawlerTaskVO.builder()
                .taskId(task.getTaskId())
                .taskName(getTaskName(task))
                .status(task.getStatus())
                .startTime(task.getStartTime().format(
                        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .endTime(task.getEndTime().format(
                        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .build();
    }

    private String getTaskName(CrawlerTask task) {
        return task.getSource() + "爬取任务" +
                (task.getScheduled() ? "(定时)" : "(手动)");
    }
}